﻿// -----------------------------------------------------------------------
// <copyright file="SQLInjectionPreventionAttribute.cs" company="Microsoft">
// TODO: Update copyright text.
// </copyright>
// -----------------------------------------------------------------------
namespace CMS.Common.Validation
{
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    using System.Web.Mvc;

    public class SqlInjectionPreventionAttribute : ValidationAttribute, IClientValidatable
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="SqlInjectionPreventionAttribute"/> class.
        /// </summary>
        public SqlInjectionPreventionAttribute()
        {
            ErrorMessage = @"Search will not be performed because the search criteria contains unsupported characters (;|--|/*|*/|xp_).";
        }

        /// <summary>
        /// Determines whether the specified value of the object is valid.
        /// </summary>
        /// <param name="value">The value of the object to validate.</param>
        /// <returns>
        /// true if the specified value is valid; otherwise, false.
        /// </returns>
        public override bool IsValid(object value)
        {
            if (value == null)
            {
                return true;
            }

            string str = value.ToString();
            for (int i = 0; i < str.Length; i++)
            {
                switch (str[i])
                {
                    case ';':
                        return false;
                    case '-':
                        if ((i + 1 < str.Length) && str[i + 1].Equals('-'))
                        {
                            return false;
                        }

                        break;
                    case '/':
                        if ((i + 1 < str.Length) && str[i + 1].Equals('*'))
                        {
                            return false;
                        }

                        break;
                    case '*':
                        if ((i + 1 < str.Length) && str[i + 1].Equals('/'))
                        {
                            return false;
                        }

                        break;
                    case 'x':
                        if ((i + 2 < str.Length) && str[i + 1].Equals('p') && str[i + 2].Equals('_'))
                        {
                            return false;
                        }

                        break;
                    default:
                        break;
                }
            }

            return true;
        }

        /// <summary>
        /// When implemented in a class, returns client validation rules for that class.
        /// </summary>
        /// <param name="metadata">The model metadata.</param>
        /// <param name="context">The controller context.</param>
        /// <returns>
        /// The client validation rules for this validator.
        /// </returns>
        public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
        {
            var rule = new ModelClientValidationRule
            {
                ValidationType = "sqlinjectionprevention",
                ErrorMessage = FormatErrorMessage(metadata.GetDisplayName())
            };

            yield return rule;
        }
    }
}